package com.soup.common.entity;

import com.soup.common.constant.CommonConstant;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 统一接口返回模型
 *
 * @author zhaoyi
 */
@Slf4j
@Data
public class Result implements Serializable {

    private int code;

    private String msg;

    /**
     * 分页返回的总条数
     */
    private Long count;

    private Object data;

    /**
     * 额外返回数据
     */
    private Map<String, Object> ext;

    public Result() {
    }

    private Result setResult(ErrorCode errorCode) {
        this.code = errorCode.getCode();
        this.msg = errorCode.getMessage();
        return this;
    }

    private Result setResult(Object codeObj, Object data) {
        int code = CommonConstant.NUM_400;
        String msg = CommonConstant.BLANK;
        Class<?> clazz = codeObj.getClass();
        try {
            Method getCode = clazz.getMethod(CommonConstant.GETCODE);
            code = (int) getCode.invoke(codeObj);
            Method getMessage = clazz.getMethod(CommonConstant.GETMESSAGE);
            msg = (String) getMessage.invoke(codeObj);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            log.error("错误对象不符合格式，没有包含{}和{}方法", CommonConstant.GETCODE, CommonConstant.GETMESSAGE);
        }

        this.code = code;
        this.msg = msg;
        this.data = data;
        return this;
    }

    private Result setResult(int code, Object data, Long count) {
        this.code = code;
        this.data = data;
        this.count = count;
        return this;
    }

    private Result setResult(int code, Object data) {
        this.code = code;
        this.data = data;
        return this;
    }

    public Result success() {
        return setResult(ErrorCode.SUCCESS);
    }

    public Result success(Object data) {
        return setResult(ErrorCode.SUCCESS, data);
    }

    public Result success(Object data, Long count) {
        return setResult(ErrorCode.SUCCESS.getCode(), data, count);
    }

    public Result fail() {
        return setResult(ErrorCode.FAILURE);
    }

    public Result fail(Object errorCode) {
        return setResult(errorCode, null);
    }

    public Result fail(Object errorCode, Object data) {
        return setResult(errorCode, data);
    }

    public Result fail(String message) {
        Result result = setResult(ErrorCode.FAILURE, null);
        result.msg = message;
        return result;
    }

    public Result fail(Object data, String message, int code) {
        this.code = code;
        this.msg = message;
        this.data = data;
        return this;
    }
}
